<template>
  <t-layout class="w-full h-full flex flex-col">
    <t-header class="flex justify-between items-center px-5 shadow">
      <span class="title text-lg">自由视角</span>
      <t-button class="justify-end" theme="primary" variant="dashed" @click="handleConfigOpen">配置</t-button>
    </t-header>

    <t-content class="w-full flex-1 align-center justify-center bg-black relative" ref="mainRef">
      <video
        class="bg-black w-full h-full absolute top-0 left-0"
        id="video-element"
        ref="videoElement"
        muted="false"
        autoplay
        playsinline
      ></video>
    </t-content>

    <t-drawer v-model:visible="configOpen" header="配置" size="700px" :show-overlay="false" destroy-on-close>
      <template #footer>
        <t-button theme="default" variant="base" @click="configOpen = false"> 关闭 </t-button>
      </template>

      <div class="config-container flex flex-col w-full h-full">
        <t-radio-group variant="default-filled" v-model:value="currentActiveKey">
          <t-radio-button value="1">输入配置</t-radio-button>
          <t-radio-button value="2">输出配置</t-radio-button>
        </t-radio-group>

        <div class="flex-1 mt-5">
          <keep-alive>
            <component
              :is="
                {
                  '1': InputConfiguration,
                  '2': OutputConfiguration
                }[currentActiveKey]
              "
            />
          </keep-alive>
        </div>
      </div>
    </t-drawer>
  </t-layout>
</template>

<script setup>
import InputConfiguration from './components/InputConfiguration.vue'
import OutputConfiguration from './components/OutputConfiguration.vue'
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { hostname, protocol, wsProtocol, webRtcStreamerPort } from '@/utils/request/config'
import { throttle } from 'lodash'
import { startStream } from '@/api/common'
import MouseEventHandler from '@/utils/mouse-event-handler'

// 请求预览拉流
let streamUrl = ''
let vPort = ''
const fetchStreamInfo = async () => {
  const res = await startStream()
  const data = res?.data || {}
  eventSocketUrl = data.controlUrl
  streamUrl = data.streamUrl
  vPort = data.vPort
  eventSocketConnect(eventSocketUrl)
  playStream()
}

fetchStreamInfo()

const playStream = () => {
  const webRtcServe = new WebRtcStreamer('video-element', `${protocol}//${hostname}:${webRtcStreamerPort}`)
  webRtcServe.connect(streamUrl, null, 'rtptransport=udp&timeout=60')
}

// 配置tabs
const currentActiveKey = ref('')
const configOpen = ref(false)
const handleConfigOpen = () => {
  configOpen.value = true
  currentActiveKey.value = '1'
}

const videoElement = ref(null)
let allowReconnect = true
let eventSocket = null
let eventRetryTimer = null
let eventSocketUrl = ''
let heartbeatInterval = null // 用于存储心跳定时器
const HEARTBEAT_INTERVAL = 3000 // 心跳间隔 3秒
const eventSocketConnect = (socketUrl) => {
  eventSocket = new WebSocket(socketUrl)

  eventSocket.onopen = () => {
    if (eventRetryTimer) {
      clearTimeout(eventRetryTimer)
      eventRetryTimer = null
    }
    console.log('Event webSocket connection')

    // 开始心跳
    startHeartbeat()
  }

  eventSocket.onclose = async () => {
    // 清理心跳定时器
    clearInterval(heartbeatInterval)

    reconnection()
    console.log('Event webSocket connection closed')
  }

  eventSocket.onerror = (error) => {
    // 清理心跳定时器
    clearInterval(heartbeatInterval)

    reconnection()
    console.error('Event webSocket error observed:', error)
  }

  function reconnection() {
    if (allowReconnect) {
      eventRetryTimer = setTimeout(() => {
        eventSocketConnect(eventSocketUrl)
      }, 5000) // 重连间隔 5秒
    }
  }
}

// 发送心跳消息
const startHeartbeat = () => {
  heartbeatInterval = setInterval(() => {
    if (eventSocket?.readyState === WebSocket.OPEN) {
      const heartbeatMessage = JSON.stringify({
        type: 100,
        vPort,
        percent: 0,
        x: 0,
        y: 0,
        width: 0,
        height: 0
      })
      eventSocket.send(heartbeatMessage)
      // console.log('Sent heartbeat: ping')
    }
  }, HEARTBEAT_INTERVAL) // 每30秒发送一次心跳
}

// 发送消息到 WebSocket
const sendWebSocketMessage = (params) => {
  if (eventSocket?.readyState === WebSocket.OPEN) {
    const queryString = JSON.stringify(params)
    eventSocket.send(queryString)
  }
}

// 事件回调
const handleEvent = (eventType, payloadParams) => {
  const { xOffsetRatio, endX, endY, playerWidth, playerHeight } = payloadParams

  const params = {
    type: eventType,
    vPort,
    percent: 1,
    x: endX,
    y: endY,
    width: playerWidth,
    height: playerHeight
  }

  sendWebSocketMessage(params)
}

// 使用封装的类来处理鼠标事件
let mouseHandler = null
onMounted(() => {
  const config = {
    ratioThreshold: 7,
    eventHandlers: {
      drag: (params) => {
        if (params.dragType !== 'x') return
        if (params.moveDirection.includes('left')) {
          handleEvent(0, params)
        } else if (params.moveDirection.includes('right')) {
          handleEvent(1, params)
        }
      },
      whell: (params) => {
        switch (params.zoom) {
          case 'in':
            handleEvent(2, params)
            break
          case 'out':
            handleEvent(3, params)
            break
        }
      }
    }
  }

  mouseHandler = new MouseEventHandler('video-element', config)
})

onBeforeUnmount(async () => {
  allowReconnect = true

  if (eventRetryTimer) {
    clearTimeout(eventRetryTimer)
    eventRetryTimer = null
  }

  if (heartbeatInterval) {
    clearInterval(heartbeatInterval)
    heartbeatInterval = null
  }

  if (eventSocket) {
    eventSocket.close()
    eventSocket = null
  }

  if (mouseHandler) {
    mouseHandler.destroy()
    mouseHandler = null
  }
})
</script>
